﻿using FreeSql;
using ManaMaple.Auth;
using ManaMaple.Core.Attributes;
using ManaMaple.Core.Filters;
using ManaMaple.DB.Context;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ManaMaple.Apollo;
using ManaMaple.Autofac;
using Com.Ctrip.Framework.Apollo.Enums;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Hosting;
using ManaMaple.Auth.Models;
using Microsoft.AspNetCore.Builder;
using ManaMaple.Core.Extensions;
using AspNetCoreRateLimit;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Prometheus;
using System.Text.Json;
using System.Net.Mime;

namespace ManaMaple.Core
{
    public static class ManaMapleCoreService
    {
        static Assembly[] Assemblies = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "ManaMaple.*.dll")
                .Select(Assembly.LoadFrom).ToArray();

        public static void AddManaMapleCoreServices(this IServiceCollection service)
        {
            service.AddControllers(options =>
            {
                //自定义异常处理服务
                //options.Filters.Add(new CustomerExceptionFilter());
                //权限处理服务
                options.Filters.Add(new CustomAuthorizationFilterAttribute());
            });
            // AutoMapper服务
            service.AddAutoMapper(Assemblies);
            #region 数据库服务
            string strConn = AppsettingsHelper.GetConfig("ConnectionStrings:mysql");
            service.AddSingleton(FreeSqlContext.GetInstance(strConn));
            service.AddFreeRepository();
            service.AddScoped<UnitOfWorkManager>();
            #endregion

            #region jwt
            var token = AppsettingsHelper.GetConfig<JwtConfig>("JwtTokens");
            service.AddJwtService(token);
            #endregion

            #region 监控与日志服务
            // 添加监控与健康检查服务
            service.AddMonitoringServices();
            
            // 添加健康检查
            service.AddHealthChecks()
                .AddCheck("系统自检", () => HealthCheckResult.Healthy());
                
            // 默认情况下，如果项目配置了MySQL连接字符串，添加MySQL健康检查
            if (!string.IsNullOrEmpty(strConn))
            {
                try
                {
                    service.AddHealthChecks()
                        .AddMySql(strConn, name: "mysql_database");
                }
                catch (Exception)
                {
                    // 如果MySQL健康检查包未安装，则忽略
                }
            }
            
            // 添加监控指标收集 - 解决二义性问题，完全移除此行，改用MonitoringServices中的方法
            // service.AddMonitoringServices().AddMetrics(); 
                
            // 添加IP限流服务
            service.AddMemoryCache();
            service.Configure<IpRateLimitOptions>(options =>
            {
                options.EnableEndpointRateLimiting = true;
                options.StackBlockedRequests = false;
                options.HttpStatusCode = 429;
                options.RealIpHeader = "X-Real-IP";
                options.ClientIdHeader = "X-ClientId";
                options.GeneralRules = new List<RateLimitRule>
                {
                    new RateLimitRule
                    {
                        Endpoint = "*",
                        Period = "1m",
                        Limit = 100
                    }
                };
            });
            service.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
            service.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
            service.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
            #endregion
        }
        
        public static void AddManaMapleCoreHost(this IHostBuilder hostBuilder)
        {
            // Apollo
            hostBuilder.AddApolloService();

            // Autofac注入
            hostBuilder.AutofacModules(Assemblies);
        }
        
        public static void AddManaMapleWebApplication(this WebApplication hostBuilder)
        {
            #region Appsettings
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{hostBuilder.Environment.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables()
                .Build();
            AppsettingsHelper.Initialize(configuration);
            #endregion
        }

        /// <summary>
        /// 添加监控和健康检查终结点
        /// </summary>
        public static void UseMonitoringEndpoints(this WebApplication app)
        {
            // 添加Prometheus指标终结点
            app.MapMetrics();
            
            // 添加健康检查终结点
            app.MapHealthChecks("/health", new HealthCheckOptions
            {
                ResponseWriter = async (context, report) =>
                {
                    var result = JsonSerializer.Serialize(
                        new
                        {
                            status = report.Status.ToString(),
                            checks = report.Entries.Select(e => new
                            {
                                name = e.Key,
                                status = e.Value.Status.ToString(),
                                description = e.Value.Description,
                                duration = e.Value.Duration
                            }),
                            totalDuration = report.TotalDuration
                        });
                    
                    context.Response.ContentType = MediaTypeNames.Application.Json;
                    
                    // 修复WriteAsync问题，直接使用Write方法
                    await context.Response.Body.WriteAsync(
                        System.Text.Encoding.UTF8.GetBytes(result), 
                        0, 
                        System.Text.Encoding.UTF8.GetByteCount(result)
                    );
                }
            });
        }
    }
}
